package com.jiliang.common.bean;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * beanCopy
 * @author
 * @version v_1.0.1
 * @since 2018/8/10 15:41
 */
public class BeanCopyDsUtil {
    public BeanCopyDsUtil() {
    }

    public static void copyProperties(Object from, Object to){
        try {
            copyPropertiesExclude(from, to, (String[]) null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception {
        List excludesList = null;
        if(excludsArray != null && excludsArray.length > 0) {
            excludesList = Arrays.asList(excludsArray);
        }

        if(from != null) {
            Method[] fromMethods = from.getClass().getMethods();
            Method[] toMethods = to.getClass().getMethods();
            Method fromMethod = null;
            Method toMethod = null;
            String fromMethodName = null;
            String toMethodName = null;

            for(int i = 0; i < fromMethods.length; ++i) {
                fromMethod = fromMethods[i];
                fromMethodName = fromMethod.getName();
                boolean get = fromMethodName.contains("get") && (excludesList == null || !excludesList.contains(fromMethodName.substring(3).toLowerCase()));
                if(get) {
                    toMethodName = "set" + fromMethodName.substring(3);
                    toMethod = findMethodByName(toMethods, toMethodName);
                    if(toMethod != null) {
                        Object value = fromMethod.invoke(from, new Object[0]);
                        if(value != null) {
                            if(value instanceof Collection) {
                                Collection newValue = (Collection)value;
                                if(newValue.size() <= 0) {
                                    continue;
                                }
                            }

                            toMethod.invoke(to, new Object[]{value});
                        }
                    }
                }
            }

        }
    }

    public static void copyPropertiesInclude(Object from, Object to, String[] includsArray) throws Exception {
        List includesList = null;
        if(includsArray != null && includsArray.length > 0) {
            includesList = Arrays.asList(includsArray);
            Method[] fromMethods = from.getClass().getDeclaredMethods();
            Method[] toMethods = to.getClass().getDeclaredMethods();
            Method fromMethod = null;
            Method toMethod = null;
            String fromMethodName = null;
            String toMethodName = null;

            for(int i = 0; i < fromMethods.length; ++i) {
                fromMethod = fromMethods[i];
                fromMethodName = fromMethod.getName();
                if(fromMethodName.contains("get")) {
                    String str = fromMethodName.substring(3);
                    if(includesList.contains(str.substring(0, 1).toLowerCase() + str.substring(1))) {
                        toMethodName = "set" + fromMethodName.substring(3);
                        toMethod = findMethodByName(toMethods, toMethodName);
                        if(toMethod != null) {
                            Object value = fromMethod.invoke(from, new Object[0]);
                            if(value != null) {
                                if(value instanceof Collection) {
                                    Collection newValue = (Collection)value;
                                    if(newValue.size() <= 0) {
                                        continue;
                                    }
                                }

                                toMethod.invoke(to, new Object[]{value});
                            }
                        }
                    }
                }
            }

        }
    }

    public static Method findMethodByName(Method[] methods, String name) {
        for(int j = 0; j < methods.length; ++j) {
            if(methods[j].getName().equals(name)) {
                return methods[j];
            }
        }

        return null;
    }
}
